package com.css.spring.formework.webmvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Map;

public class HandlerAdapter {
    private Map<String, Integer> paramMapping;

    public HandlerAdapter(Map<String, Integer> paramMapping) {
        this.paramMapping = paramMapping;

    }

    public ModelAndView handle(HttpServletRequest req, HttpServletResponse resp, HandlerMapping handlerMapping) throws InvocationTargetException, IllegalAccessException {

        Class<?>[] parameterTypes = handlerMapping.getMethod().getParameterTypes();

        Map<String, String[]> reqParameterMap = req.getParameterMap();

        Object[] paramValues = new Object[parameterTypes.length];

        for (Map.Entry<String, String[]> stringEntry : reqParameterMap.entrySet()) {

            String key = stringEntry.getKey();
            if (paramMapping.containsKey(key)) {
                Integer index = paramMapping.get(key);
                paramValues[index] =

                        caseStringValue(Arrays.toString(stringEntry.getValue()).replaceAll("\\[|\\]", "")
                                .replaceAll("\\s", ","), parameterTypes[index]);
            }
        }
        Integer reqIndex = paramMapping.get(HttpServletRequest.class.getName());
        if (reqIndex != null) {
            paramValues[reqIndex] = req;

        }
        Integer respIndex = paramMapping.get(HttpServletResponse.class.getName());
        if (respIndex != null) {
            paramValues[respIndex] = resp;
        }
        Object result = handlerMapping.getMethod().invoke(handlerMapping.getController(), paramValues);
        if (result != null && handlerMapping.getMethod().getReturnType() == ModelAndView.class) {
            return (ModelAndView) result;
        } else {
            return null;
        }
    }

    private Object caseStringValue(String value, Class<?> aClass) {
        if (aClass == String.class) {
            return value;
        } else if (aClass == Integer.class) {
            return Integer.valueOf(value);
        } else if (aClass == int.class) {
            return Integer.valueOf(value).intValue();
        } else {
            return null;
        }
    }
}
